#include "pagerank.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "vector.h"
#include "stats.h"

int *pagerank_pm (double* pi, Digraph H, double alpha, double epsilon)
{
  double *ans1, *ans2, *old_pi;
  double residual = 1.0;
  double time;
  int iter = 0;
  int t0, t1, i;
  int *rank;
  Vertex v;

  ans1   = malloc(H->V * sizeof(double));
  ans2   = malloc(H->V * sizeof(double));
  old_pi = malloc(H->V * sizeof(double));
  for (i = 0; i < H->V; i++) pi[i] = 1.0 / H->V;

  //Power Method iteration
  t0 = clock();
  while (residual >= epsilon) {
    // Store previous PI
    for (v = 0; v < H->V; v++) old_pi[v] = pi[v];
    iter++;

    //Calculate next PI
    calc_pt1(pi, H, alpha, ans1);
    calc_pt2(pi, H, alpha, ans2);
    point_sum(ans1, ans2, pi, H->V);

    //Calculate residual
    point_sub(pi, old_pi, old_pi, H->V);
    residual = norm1(old_pi, H->V);
  }
  t1 = clock();
  time = ((double)(t1 - t0)) / CLOCKS_PER_SEC;

  rank = find_top_values(pi, H->V, H->V);
  print_stats(H, iter, time, alpha, epsilon, "PageRank", "alpha");

  free(old_pi);
  free(ans1);
  free(ans2);

  return rank;
}

void calc_pt1 (double *pi, Digraph H, double alpha, double *ans)
{
  Vertex v;
  link list;

  for (v = 0; v < H->V; v++) ans[v] = 0;

  for (v = 0; v < H->V; v++) {
    list = H->adj[v];
    while (list != NULL) {
      ans[list->w] += pi[v] * (1.0 / H->out[v]) * alpha;
      list = list->next;
    }
  }
}

void calc_pt2 (double *pi, Digraph H, double alpha, double *ans) 
{
  Vertex v;
  double inner;
  double value;

  inner = inner_product(pi, H->dng, H->V);
  value = (1.0 / H->V) * ((alpha * inner) + (1.0 - alpha));
  for (v = 0; v < H->V; v++) ans[v] = value;
}

void print_pr(double *rank, int V)
{
  Vertex v;

  for (v = 0; v < V; v++) {
    if(v % 10 == 0) printf("\n");
    printf("PR[%d] = %.5f | ", v, rank[v]);
  }
  printf("\n");
}

